import React, { useEffect } from 'react';
// import csvData from './data/data.csv';
import jsonData from './data/data.json';
import * as d3 from 'd3';
import './style/5.css';

const WeatherChart = function () {

    useEffect(() => {
        d3.select('svg').selectAll('*').remove();

        var content = d3.select(".weather-chart")
        var margin = {
            top: 40,
            right: 50,
            bottom: 40,
            left: 50
        };
        let contentWidth = content.style('width').substring(0, content.style('width').length - 2)
        let contentHeight = content.style('height').substring(0, content.style('height').length - 2)

        var width = contentWidth - margin.left - margin.right;
        var height = contentHeight - margin.top - margin.bottom;

        var svg = d3.select("body").select("svg")
            .attr('width', width)
            .attr('height', height)
        let chartContainer = svg.append("g").attr('class', 'chart-container')
            .attr("width", width).attr("height", height)
            .attr("transform", "translate(" + margin.left + "," + (margin.top) + ")");

        // var parseDate = d3.timeFormat("%d-%b-%y").parse;
        // var bisectDate = d3.bisector(function(d) {
        //     return d.time;
        // }).left;
        // var formatValue = d3.format(",.2f");
        // var formatCurrency = function(d) {
        //     return "$" + formatValue(d);
        // };

        var data = jsonData.data.map((item) => {
            if (item.tmp) {
                return { ...item }
            } else {
                return { ...item, tmp: 0 }
            }
        });

        // 最高气温
        var maxDataTmp = 0;
        // 最低气温
        var minDataTmp = 0;
        data.forEach(function (d) {
            d.time = new Date(d.time).valueOf();
            d.tmp = +d.tmp;
            if (d.tmp > maxDataTmp) {
                maxDataTmp = d.tmp;
            }
            if (d.tmp < minDataTmp) {
                minDataTmp = d.tmp
            }
        });

        var x = d3.scaleTime()
            .range([0, width])
            .domain([data[0].time, data[data.length - 1].time]);

        var y = d3.scaleLinear()
            .range([height, 0])
            .domain([minDataTmp, maxDataTmp])

        // 横坐标
        var xAxis = d3.axisBottom()
            .scale(x).ticks(d3.timeHour.every(2)).tickFormat(d3.timeFormat("%d %I:%M"));

        chartContainer.append("g")
            .attr("class", "x-axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        //添加文字元素
        chartContainer.append("g")
            .attr("class", "my-text")
            .selectAll(".my-text")
            .data(data)
            .enter()
            .append("text")
            .attr("transform", "translate(-8, -5)")
            // .attr("transform","translate(" + xScale.bandwidth()/2 + "," + padding.top + ")")
            .attr("x", function (d, i) {
                return x(d.time);
            })
            .attr("y", function (d) {
                return y(d.tmp);
            })
            .text(function (d) {
                return d.tmp + "°";
            });

        // 线
        const line = d3.line()
            .x(d => x(d.time))
            .y(d => y(d.tmp))
            .curve(d3.curveCatmullRom.alpha(0.5));

        const createTempGradient = select => {
            const gradient = select
                .select('#maskDefs')
                .append('linearGradient')
                .attr('id', 'tempGradient')
                .attr('x1', '0%')
                .attr('y1', '0%')
                .attr('x2', '100%')
                .attr('y2', '0%');

            const step = 100 / data.length;
            const colors = [
                'rgba(131, 239, 212, 1)',
                'rgba(189, 255, 167, 1)',
                'rgba(255, 219, 140, 1)',
                'rgba(255, 123, 119, 1)',
            ]; // 从温度从低到高颜色排序
            data.forEach((item, index) => {
                let level = 0;
                if (item.tmp < 10) {
                    level = 0
                } else if (item.tmp >= 10 && item.tmp < 18) {
                    level = 1
                } else if (item.tmp >= 18 && item.tmp < 27) {
                    level = 2
                } else if (item.tmp >= 27) {
                    level = 3
                }
                return gradient
                    .append('stop')
                    .attr('offset', `${step * index}%`)
                    .attr('stop-color', colors[level])
            })
        }

        const createOpacityGradient = select => {
            const gradient = select
                .select('#maskDefs')
                .append('linearGradient')
                .attr('id', 'opacityGradient')
                .attr('x1', '0%')
                .attr('y1', '0%')
                .attr('x2', '0%')
                .attr('y2', '100%');
            const step = 100 / data.length;
            data.forEach((item, index) => {
                return gradient
                    .append('stop')
                    .attr('offset', `${step * index}%`)
                    .attr('stop-color', '#c4c4c4')
                    .attr('stop-opacity', `${1 - step * index / 100}`)
            })
        }

        let maskDefs = chartContainer.append('defs').attr('id', 'maskDefs');
        chartContainer.call(createTempGradient);
        chartContainer.call(createOpacityGradient);

        // 创建一个 <mask> 元素
        const mask = maskDefs.append('mask').attr('id', 'opacityMask');

        // 向 <mask> 元素中添加一个 <rect> 元素作为蒙版
        mask.append('rect')
            .attr('x', 0)
            .attr('y', 0)
            .attr('width', width) // 假设 width 为线条的宽度
            .attr('height', height) // 假设 height 为线条的高度
            .attr('fill', 'url(#opacityGradient)'); // 可以使用线条的填充颜色作为蒙版的颜色

        chartContainer.append("path")
            .datum(data)
            .attr("class", "line")
            .attr("d", line)
            .attr('stroke-width', '1')
            .style('fill', 'none')
            .attr('stroke', '#eee')

        let lineD = ""
        chartContainer.select('.line')
            .style('d', d => {
                lineD = line(d).slice(1)
            })

        chartContainer.append("path")
            .attr("class", "line-gradient")
            .attr("d", d => {
                const splitedValues = lineD.split(',');
                return `M0,${height},${lineD},l0,${height - splitedValues[splitedValues.length - 1]}`
            })
            .style('fill', 'url(#tempGradient)')
            .style('mask', 'url(#opacityMask)') // 将蒙版应用到线条上

        // 动效
        // 创建pattern
        let animateDefs = chartContainer.append("defs").attr("id", "animateDefs")
        let pattern = animateDefs.append("pattern")
            .attr("id", "patternRainAreaAnim")
            .attr("width", 3104)
            .attr("height", 207)
            .attr("patternUnits", "userSpaceOnUse")

        // pattern.append("image").attr("href", "http://localhost:3000/weather-img/rain-avg.png")
        // pattern.append("image").attr("href", "http://localhost:3000/weather-img/snow-avg.png")
        // pattern.append("image").attr("href", "http://localhost:3000/weather-img/sleet-avg.png")
        // pattern.append("image").attr("href", "http://localhost:3000/weather-img/sleet-nosplash-avg.png")
        pattern.append("image").attr("href", "http://localhost:3000/weather-img/rain-nosplash-avg.png")
            .attr("width", 3104)
            .attr("height", 207)

        // 创建 animate 元素
        pattern.append("animate")
            .attr("attributeType", "XML")
            .attr("attributeName", "x")
            .attr("calcMode", "discrete")
            .attr("dur", "1s")
            .attr("repeatCount", "indefinite")
            .attr("values", "0;-206.99999999999997;-413.99999999999994;-620.9999999999999;-827.9999999999999;-1034.9999999999998;-1241.9999999999998;-1448.9999999999998;-1655.9999999999998;-1862.9999999999998;-2069.9999999999995;-2276.9999999999995;-2483.9999999999995;-2690.9999999999995;-2897.9999999999995;")

        // 增加rect动效
        chartContainer.append("g")
            .attr("class", "rect-animate")
            .append('rect')
            .attr('x', 0)
            .attr('y', 0)
            .attr('width', 200)
            .attr('height', height)
            .attr('fill', 'url(#patternRainAreaAnim)');
    }, [])

    return (
        <div className="weather-chart">
            <svg className="chart-show"></svg>
        </div>
    )
}

export default WeatherChart